/* 
 * Copyright 2011 kOSMik.
 * This file is part of kOSMik.
 * 
 * kOSMik is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * kOSMik is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with kOSMik.  If not, see <http://www.gnu.org/licenses/>.
 *  
 * kOSMik:
 * Open Street Map - Editor.
 * http://code.google.com/p/swp-dv-ws2010-osm-2/
 */

package de.fuberlin.kosmik.export;

import java.io.OutputStream;
import java.io.PrintWriter;
import java.util.Map;

/**
 * Simple class that can be used to write a basic XML-Structure into a
 * PrintWriter. PrintWriter is used as it avoids an endless try-catch orgy...
 * 
 * @author Simon
 */
public class XmlWriter {

	private static final String BEGIN_TAG = "<";
	private static final String END_TAG = ">";
	private static final String END_ELEMENT = "/";
	private static final String DECLARATION = "<?xml version=\'1.0\' encoding=\'UTF-8\'?>";
	private static final String SPACE = " ";
	private static final String BEGIN_ASSIGNMENT = "=\"";
	private static final String END_ASSIGNMENT = "\" ";

	private PrintWriter out;

	/**
	 * Constructs a new XmlWriter object.
	 * 
	 * @param transport stream to write to.
	 */
	public XmlWriter(OutputStream transport) {
		this.out = new PrintWriter(transport);

	}

	/**
	 * Write the XML-Declaration. Should be done first.
	 */
	public void declaration() {
		out.println(DECLARATION);
	}

	/**
	 * Open a single element. The element will not be closed!
	 * 
	 * @param name of the element to open.
	 */
	public void element(String name) {
		out.println(BEGIN_TAG + name + END_TAG);
	}

	/**
	 * Open an element with attributes. The element will not be closed! <name
	 * a="" b="">
	 * 
	 * @param name of the element to open
	 * @param attributes map of the attributes.
	 */
	public void elementWithAttributes(String name, Map<String, String> attributes) {
		StringBuilder builder = new StringBuilder();

		builder.append(BEGIN_TAG + name + SPACE);

		for (Map.Entry<String, String> entry : attributes.entrySet()) {
			builder.append(assignment(entry.getKey(), entry.getValue()));
		}

		builder.append(END_TAG);

		out.println(builder.toString());

	}

	/**
	 * Creates an empty Element with the given attributes. <name a="" b="" />
	 * 
	 * @param name name of the element.
	 * @param attributes attributes of the element.
	 */
	public void emptyElementWithAttributes(String name, Map<String, String> attributes) {
		StringBuilder builder = new StringBuilder();
		builder.append(BEGIN_TAG + name + SPACE);

		for (Map.Entry<String, String> entry : attributes.entrySet()) {
			builder.append(assignment(entry.getKey(), entry.getValue()));
		}

		builder.append(END_ELEMENT + END_TAG);

		out.println(builder.toString());

	}

	/**
	 * End an element.
	 * 
	 * @param name name of the element to close
	 */
	public void endElement(String name) {
		out.println(BEGIN_TAG + END_ELEMENT + name + END_TAG);
	}

	/**
	 * Write arbitrary content.
	 * 
	 * @param content content to write.
	 */
	public void content(String content) {
		out.println(content);
	}

	private String assignment(String key, String value) {
		return key + BEGIN_ASSIGNMENT + value + END_ASSIGNMENT;
	}

	/**
	 * Flush and close stream.
	 */
	public void finish() {
		out.flush();
		out.close();
	}

}
